import type { Router } from 'vue-router';

import { LOGIN_PATH, NOT_PERMISSION_PATH } from '@croco/framework/constants';
import { preferences } from '@croco/framework/preferences';
import { useUserStore } from '@croco/framework/stores';
import { startProgress, stopProgress } from '@croco/framework/utils';

import { getUserDetails, getUserPermissions } from '#/api';
import { accessRoutes, coreRouteNames } from '#/router/routes';

import { generateAccess } from './access';

/**
 * 通用守卫配置
 * @param router
 */
function setupCommonGuard(router: Router) {
    // 记录已经加载的页面
    const loadedPaths = new Set<string>();

    router.beforeEach((to) => {
        to.meta.loaded = loadedPaths.has(to.path);

        // 页面加载进度条
        if (!to.meta.loaded && preferences.transition.progress) {
            startProgress();
        }
        return true;
    });

    router.afterEach((to) => {
        // 记录页面是否加载,如果已经加载，后续的页面切换动画等效果不在重复执行

        loadedPaths.add(to.path);

        // 关闭页面加载进度条
        if (preferences.transition.progress) {
            stopProgress();
        }
    });
}

/**
 * 权限访问守卫配置
 * @param router
 */
function setupAccessGuard(router: Router) {
    router.beforeEach(async (to, from) => {
        const userStore = useUserStore();

        // 基本路由，这些路由不需要进入权限拦截
        if (coreRouteNames.includes(to.name as string)) {
            if (to.path === LOGIN_PATH && userStore.loginUser?.token) {
                return decodeURIComponent((to.query?.redirect as string) || userStore.userInfo?.homePath || preferences.app.defaultHomePath);
            }
            return true;
        }

        // accessToken 检查
        if (!userStore.loginUser?.token) {
            // 明确声明忽略权限访问权限，则可以访问
            if (to.meta.ignoreAccess) {
                return true;
            }

            // 没有访问权限，跳转登录页面
            if (to.fullPath !== LOGIN_PATH) {
                return {
                    path: LOGIN_PATH,
                    // 如不需要，直接删除 query
                    query: to.fullPath === preferences.app.defaultHomePath ? {} : { redirect: encodeURIComponent(to.fullPath) },
                    // 携带当前跳转的页面，登录后重新跳转该页面
                    replace: true,
                };
            }
            return to;
        }

        // 是否已经生成过动态路由
        if (userStore.isAccessChecked) {
            return true;
        }

        // 生成路由表
        // 当前登录用户拥有的角色标识列表
        if (!userStore.userInfo) {
            const [details, permissions] = await Promise.all([getUserDetails(), getUserPermissions()]);
            userStore.setUserInfo(details);
            userStore.setAccessPerms(permissions);
        }
        const userInfo = userStore.userInfo;
        const userRoles = userInfo.roles ?? [];

        // 生成菜单和路由
        const { accessibleMenus, accessibleRoutes } = await generateAccess({
            roles: userRoles,
            router,
            // 则会在菜单中显示，但是访问会被重定向到403
            routes: accessRoutes,
        });

        // 保存菜单信息和路由信息
        userStore.setAccessMenus(accessibleMenus);
        userStore.setAccessRoutes(accessibleRoutes);
        userStore.setIsAccessChecked(true);
        // 目标路由 = 默认路由/申请权限路由或者用户默认路由 = 申请权限路由，则优先选使用用户默认路由作为重定向路由
        const redirectPath = (from.query.redirect ??
            (to.path === preferences.app.defaultHomePath || userInfo.homePath === NOT_PERMISSION_PATH || to.path === NOT_PERMISSION_PATH
                ? userInfo.homePath || preferences.app.defaultHomePath
                : to.fullPath)) as string;
        return {
            ...router.resolve(decodeURIComponent(redirectPath)),
            replace: true,
        };
    });
}

/**
 * 项目守卫配置
 * @param router
 */
function createRouterGuard(router: Router) {
    /** 通用 */
    setupCommonGuard(router);
    /** 权限访问 */
    setupAccessGuard(router);
}

export { createRouterGuard };
